﻿module Sustainalytics.Insights.Admin {

    import Common = Sustainalytics.Common;
    import CommonAdmin = Sustainalytics.Common.Admin;

    export class InsightsBackendService {

        private $q: ng.IQService;
        private $http: ng.IHttpService;
        private notificationFactory: Common.INotificationFactory;
        private staticObjectsAdmin: CommonAdmin.IStaticObjects;
        private $location: ng.ILocationService;
        private $upload: any;
        private internalTable = {};

        constructor(
            $q: ng.IQService,
            $http: ng.IHttpService,
            $location: ng.ILocationService,
            notificationFactory: Common.INotificationFactory,
            staticObjectsAdmin: CommonAdmin.IStaticObjects,
            $upload: any) {

            this.$q = $q;
            this.$http = $http;
            this.notificationFactory = notificationFactory;
            this.staticObjectsAdmin = staticObjectsAdmin;
            this.$location = $location;
            this.$upload = $upload;
        }

        private insightsUrl(): string{
             var ctx = this;
            return ctx.$location.protocol() + "://" + ctx.$location.host() + ":" + ctx.$location.port() + "/insightsserv/api/v1/insights/";
        }
        private helperUrl(): string {
            var ctx = this;
            return ctx.$location.protocol() + "://" + ctx.$location.host() + ":" + ctx.$location.port() + "/insightsserv/api/v1/insightsnames/";
        }
        private filesUrl(): string {
            var ctx = this;
            return ctx.$location.protocol() + "://" + ctx.$location.host() + ":" + ctx.$location.port() + "/insightsserv/api/v1/files/";
        }

        public putSetting(key: string, value: any) {
            var ctx = this;
            ctx.internalTable[key] = value;
            console.log(key + "=" + value);
        }

        public getSetting(key: string): any {
            var ctx = this;
            if (ctx.internalTable[key])
                return ctx.internalTable[key];
            return null;
        }

        public insightGetCount(filter: InsightFilterDto): ng.IPromise<number> {
            
            var ctx = this;
            if (!filter)
                filter = new InsightFilterDto();

            var def = ctx.$q.defer();

            var promise = ctx.$http.get(ctx.insightsUrl(), { params: $.extend({ fromAdmin: true, getcount: true }, filter) });
            promise
                .success(data => { def.resolve((<{ count: number }>data).count ); })
                .error(err => { ctx.showError(err); def.reject(); });
            return def.promise;
        }

        public insightGetList(filter: InsightFilterDto, gridOpt: CommonAdmin.HttpGetOptionsDto): ng.IPromise<InsightDto[]> {
            
            var ctx = this;

            if (!filter)
                filter = new InsightFilterDto();
            var def = this.$q.defer();
            
            var promise = this.$http.get(ctx.insightsUrl(), { params: $.extend({ fromAdmin: true }, filter, gridOpt) } );
            promise
                .success(data => { def.resolve(data); })
                .error(err => { ctx.showError(err); def.reject(); });
            return def.promise;
        }

        public getNomenclators(): ng.IPromise<InsightHelperDto> {

            var ctx = this;
            if (ctx.internalTable["getNomenclators"]) {
                console.log("from local cache");
                return  this.$q.when(ctx.internalTable["getNomenclators"]);
            } else {

                var def = this.$q.defer();
                
                var promise = this.$http.get(ctx.helperUrl());
                promise
                    .success(data => {
                        ctx.internalTable["getNomenclators"] = data;
                        def.resolve(data);
                    })
                    .error(err => { ctx.showError(err); def.reject(); });
                return def.promise;
            }
        }

        public insightGet(id: string): ng.IPromise<InsightDto> {

            var ctx = this;
            var def = this.$q.defer();
            var promise = this.$http.get(ctx.insightsUrl() + id, { params: { includeAllFields: true, fromAdmin: true } });
            promise
                .success(data => { def.resolve(data); })
                .error(err => { ctx.showError(err); def.reject(); });
            return def.promise;
        }

        public insightCreateOrUpdate(dto: InsightDtoUi): ng.IPromise<boolean> {
            
            var ctx = this;
            var def = ctx.$q.defer();

            console.log(dto);
            var promise: ng.IHttpPromise<{}>;
            
            if (dto.id)
                promise = ctx.$http.put(ctx.insightsUrl(), dto);
            else
                promise = ctx.$http.post(ctx.insightsUrl(), dto);
            promise
                .success(data => { def.resolve(true); })
                .error(err => { ctx.showError(err); def.reject(); });
            return def.promise;
        }

        public fileUpload(file: File, id: string): ng.IPromise<{}> {

            var ctx = this;
            var def = ctx.$q.defer();

            var reader = new FileReader();
            reader.onload = (data) => {
                return ctx.$upload.http({
                    method: (id) ? "PUT" : "POST",
                    url: ctx.filesUrl() + ((id) ? id : ""),
                    headers: { 'Content-Disposition': 'attachment; filename=\"' + file.name + "\"", 'Content-Type': file.type, },
                    data: reader.result
                })
                    .progress(evt => { console.log('percent: ' + (100.0 * evt.loaded / evt.total)); })
                    .success((data, status, headers, config) => { def.resolve(data)});
            };
            reader.readAsArrayBuffer(file);
            return def.promise;
        }

        public insightDelete(items: InsightDtoUi[]): ng.IPromise<boolean> {
            
            var ctx = this;
            var def = this.$q.defer();


            var ops : InsightPathcOpDto[] = [];
            items.forEach((item) => {
                var newop = new InsightPathcOpDto();
                newop.resourceid = item.id;
                newop.verb = "DELETE";
                ops.push(newop);
            });

            var promise = ctx.$http({ method: "PATCH", url: ctx.insightsUrl(), data: ops });
            promise
                .success(data => { def.resolve(data); })
                .error(err => { ctx.showError(err); def.reject(); });
            return def.promise;
        }

        public insightUpdate(items: InsightDtoUi[], newstate: number ): ng.IPromise<boolean> {

            var ctx = this;
            var def = this.$q.defer();


            var ops: InsightPathcOpDto[] = [];
            items.forEach((item) => {
                var newop = new InsightPathcOpDto();
                newop.resourceid = item.id;
                newop.verb = "PATCH";
                newop.newState = newstate.toString();
                ops.push(newop);
            });

            var promise = ctx.$http({ method: "PATCH", url: ctx.insightsUrl(), data: ops });
            promise
                .success(data => { def.resolve(data); })
                .error(err => { ctx.showError(err); def.reject(); });
            return def.promise;
        }
        
        // show error message for a given error code
        private showError(err) {
            var ctx = this;
            if (err && err['errorCode'])
                ctx.notificationFactory.error('', ctx.staticObjectsAdmin.getMessageByInternalCode(err['errorCode']));
        }

    }

    // register service with Insights Angular module
    var mod = angular.module(insightsAdminModuleName);

    mod.service('InsightsBackendService',
        ['$q', '$http', '$location', 'notificationFactory', 'staticObjectsAdmin', '$upload', InsightsBackendService]);
}